package com.tree.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tree.backend.entity.dto.costItem.CostItemCreateDTO;
import com.tree.backend.entity.dto.costItem.CostItemQueryDTO;
import com.tree.backend.entity.dto.costItem.CostItemUpdateDTO;
import com.tree.backend.mapper.CostItemMapper;
import com.tree.backend.entity.pojo.CostItem;
import com.tree.backend.entity.vo.costItem.CostItemTreeNodeVO;
import com.tree.backend.entity.vo.costItem.CostItemVO;
import com.tree.backend.service.ICostItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 成本项目分类表 服务实现类
 * </p>
 */
@Service
public class CostItemServiceImpl extends ServiceImpl<CostItemMapper, CostItem> implements ICostItemService {

    @Override
    public IPage<CostItemVO> getCostItemPage(CostItemQueryDTO queryDTO) {
        // 创建分页对象
        IPage<CostItem> page = new Page<>(queryDTO.getPage(), queryDTO.getPageSize());
        
        // 构建查询条件
        QueryWrapper<CostItem> wrapper = new QueryWrapper<>();
        if (StringUtils.hasText(queryDTO.getItemName())) {
            wrapper.like("item_name", queryDTO.getItemName());
        }
        if (StringUtils.hasText(queryDTO.getItemCode())) {
            wrapper.like("item_code", queryDTO.getItemCode());
        }
        if (queryDTO.getItemType() != null) {
            wrapper.eq("item_type", queryDTO.getItemType());
        }
        if (queryDTO.getStatus() != null) {
            wrapper.eq("status", queryDTO.getStatus());
        }
        
        // 执行分页查询
        IPage<CostItem> costItemPage = this.page(page, wrapper);
        
        // 转换为VO对象
        return costItemPage.convert(this::convertToVO);
    }

    @Override
    public CostItemVO getCostItemById(Long id) {
        CostItem costItem = this.getById(id);
        if (costItem == null) {
            throw new RuntimeException("成本项目不存在");
        }
        return convertToVO(costItem);
    }

    @Override
    public boolean addCostItem(CostItemCreateDTO createDTO) {
        // 检查编码是否已存在
        QueryWrapper<CostItem> wrapper = new QueryWrapper<>();
        wrapper.eq("item_code", createDTO.getItemCode());
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("成本项目编码已存在");
        }
        
        // 创建成本项目
        CostItem costItem = new CostItem();
        BeanUtils.copyProperties(createDTO, costItem);
        
        // 设置默认值
        if (costItem.getParentId() == null) {
            costItem.setParentId(0L);
        }
        if (costItem.getBudgetCycle() == null) {
            costItem.setBudgetCycle(1);
        }
        if (costItem.getIsLeaf() == null) {
            costItem.setIsLeaf(1);
        }
        if (costItem.getStatus() == null) {
            costItem.setStatus(1);
        }
        if (costItem.getSortOrder() == null) {
            costItem.setSortOrder(0);
        }
        
        // 如果有父项目，更新父项目的叶子节点状态
        if (costItem.getParentId() > 0) {
            updateParentLeafStatus(costItem.getParentId());
        }
        
        return this.save(costItem);
    }

    @Override
    public boolean updateCostItem(Long id, CostItemUpdateDTO updateDTO) {
        CostItem costItem = this.getById(id);
        if (costItem == null) {
            throw new RuntimeException("成本项目不存在");
        }
        
        // 保存旧的父ID
        Long oldParentId = costItem.getParentId();
        
        // 更新字段
        BeanUtils.copyProperties(updateDTO, costItem);
        costItem.setId(id);
        
        boolean result = this.updateById(costItem);
        
        // 如果父ID发生变化，更新父项目的叶子节点状态
        if (result && !Objects.equals(oldParentId, costItem.getParentId())) {
            if (oldParentId > 0) {
                updateParentLeafStatus(oldParentId);
            }
            if (costItem.getParentId() > 0) {
                updateParentLeafStatus(costItem.getParentId());
            }
        }
        
        return result;
    }

    @Override
    public boolean deleteCostItem(Long id) {
        CostItem costItem = this.getById(id);
        if (costItem == null) {
            throw new RuntimeException("成本项目不存在");
        }
        
        // 检查是否有子项目
        QueryWrapper<CostItem> childWrapper = new QueryWrapper<>();
        childWrapper.eq("parent_id", id);
        if (this.count(childWrapper) > 0) {
            throw new RuntimeException("该项目下有子项目，无法删除");
        }
        
        boolean result = this.removeById(id);
        
        // 更新父项目的叶子节点状态
        if (result && costItem.getParentId() > 0) {
            updateParentLeafStatus(costItem.getParentId());
        }
        
        return result;
    }

    @Override
    public List<CostItemVO> getAllCostItems() {
        // 查询所有启用状态的成本项目
        QueryWrapper<CostItem> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1) // 只查询启用状态的成本项目
               .orderByAsc("sort_order"); // 按排序号排序
        
        List<CostItem> costItems = this.list(wrapper);
        
        // 转换为VO列表
        return costItems.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<CostItemTreeNodeVO> getCostItemTree() {
        // 获取所有成本项目
        List<CostItem> costItems = this.list();
        
        // 转换为树节点
        List<CostItemTreeNodeVO> nodes = costItems.stream()
                .map(this::convertToTreeNodeVO).toList();
        
        // 构建树结构
        Map<Long, CostItemTreeNodeVO> nodeMap = nodes.stream()
                .collect(Collectors.toMap(CostItemTreeNodeVO::getId, node -> node));
        
        List<CostItemTreeNodeVO> rootNodes = new ArrayList<>();
        
        for (CostItemTreeNodeVO node : nodes) {
            if (node.getParentId() == 0) {
                // 根节点
                rootNodes.add(node);
            } else {
                // 子节点，添加到父节点的children中
                CostItemTreeNodeVO parentNode = nodeMap.get(node.getParentId());
                if (parentNode != null) {
                    if (parentNode.getChildren() == null) {
                        parentNode.setChildren(new ArrayList<>());
                    }
                    parentNode.getChildren().add(node);
                }
            }
        }
        
        // 递归排序节点
        for (CostItemTreeNodeVO rootNode : rootNodes) {
            sortTreeNode(rootNode.getChildren());
        }
        
        return rootNodes;
    }

    /**
     * 转换为VO对象
     */
    private CostItemVO convertToVO(CostItem costItem) {
        CostItemVO vo = new CostItemVO();
        BeanUtils.copyProperties(costItem, vo);
        return vo;
    }

    /**
     * 转换为树节点VO对象
     */
    private CostItemTreeNodeVO convertToTreeNodeVO(CostItem costItem) {
        CostItemTreeNodeVO node = new CostItemTreeNodeVO();
        BeanUtils.copyProperties(costItem, node);
        return node;
    }

    /**
     * 更新父项目的叶子节点状态
     */
    private void updateParentLeafStatus(Long parentId) {
        QueryWrapper<CostItem> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", parentId);
        int childCount = (int) this.count(wrapper);
        
        CostItem parentItem = this.getById(parentId);
        if (parentItem != null) {
            parentItem.setIsLeaf(childCount > 0 ? 0 : 1);
            parentItem.setUpdateTime(LocalDateTime.now());
            this.updateById(parentItem);
        }
    }

    /**
     * 递归排序树节点
     */
    private void sortTreeNode(List<CostItemTreeNodeVO> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return;
        }
        
        // 按ID排序（简单处理，实际应该按sortOrder）
        nodes.sort(Comparator.comparing(CostItemTreeNodeVO::getId));
        
        // 递归排序子节点
        for (CostItemTreeNodeVO node : nodes) {
            sortTreeNode(node.getChildren());
        }
    }
}
